;############
;### MAIN ###
;############
(defmodule MAIN (export ?ALL))


(defrule MAIN::inicio
    (initial-fact)
    =>
    (printout t "####################################" crlf)
	(printout t "#### PLANIFICADOR DE EJERCICIOS ####" crlf)
	(printout t "####################################" crlf)
    (assert (preguntas-iniciales ok))
    (focus modulo-obtencion)
)

(deftemplate Programa "Contiene el programa de ejercicios"
	(multislot ejercicios)
)

;###########################
;## METODOS DE LAS CLASES ##
;###########################

;# Funcion que calcula las calorias consumidas
;# nota: el tiempo se expresa en unidades de 10 minutos	
(deffunction calcula-calorias (?peso ?tiempo ?consumoEnergetico ?sexo )
	(if (eq ?sexo macho)
	then (bind ?factorSexo 1.0)
	else (bind ?facotrSexo 0.9)	
	)

	(* ?peso(* ?tiempo (* 10 (* ?consumoEnergetico ?factorSexo))))
)

;# Anadimos algunas funciones a las clases
(defmessage-handler Ejercicio imprimir ()
	(format t   "[%s]%n"  ?self:nombreEjercicio)
	(format t   "    %d -> %d puntos%n" ?self:puntuacion ?self:puntuacionTemporal)
	(format t   "    DuracionMaxima: %d'%n" (* ?self:duracionMaxima 10))
	(format t   "    DuracionMinima: %d'%n" (* ?self:duracionMinima 10))
	(printout t "    Perjudica: " ?self:perjudica crlf)
	(printout t "    Beneficia: " ?self:beneficia crlf)
	(printout t "    Satisface: " ?self:satisface crlf)
)

(defmessage-handler Ejercicio descripcion (?intensidad ?duracion)
	(if (eq ?intensidad suave) then
		(bind ?descripcion ?self:descripcionSuave)
	else
		(bind ?descripcion ?self:descripcionIntensa)
	)
	(format t   "    %s %s, %d'%n"  ?self:nombreEjercicio ?descripcion (* ?duracion 10))
)

(defmessage-handler Persona imprimir ()
	(format t   "[%s]========================================%n" ?self:nombrePersona)
	(format t   "    Altura: %.2f m%n" ?self:altura)
	(format t   "    Peso: %.2f kg%n" ?self:peso)
	(format t   "    Gasto energetico: %.2f por dia%n" ?self:gastoEnergeticoDiario)
	(printout t "    Problemas: " ?self:problemas crlf)
	(printout t "    Objetivos: " ?self:objetivos crlf)
	(printout t "    Actividades: " ?self:actividades crlf)
	;#(printout t "    Tiempo: " ?self:tiempoDisponible crlf)
)

(defmessage-handler Persona IMC ()
	(/ ?self:peso (* ?self:altura ?self:altura))
)

(defmessage-handler Persona constanteMetabolismoBasal ()
	(if (eq ?self:sexo macho) then 1.0 else	0.9)
)

;# Calculo del gasto energetico total a partir del gasto energetico
;# que supone cada una de las actividades que realiza una persona
(defmessage-handler Persona calcularGastoEnergeticoDiario ()
	(bind ?total 0.0)
	(loop-for-count (?i 1 (length ?self:actividades))
		(bind ?actividad (nth$ ?i ?self:actividades))
		(bind ?tiempo (send ?actividad get-duracionTemporal))
		(bind ?ce (send ?actividad get-ce))
		(bind ?constante (send ?self constanteMetabolismoBasal))
		(bind ?gasto-energetico (* ?tiempo ?ce ?constante))
		(bind ?total (+ ?total ?gasto-energetico))
	)
	(send ?self put-gastoEnergeticoDiario ?total)
)

;#Elimina de la lista de instancias aquellas que por el multislot sl no contengan valor const
;#El primer parámetro es la lista de instancia.
;#El segundo parámetro es el método con el que se accede al slot.
;#El tercer parámetro es el valor con que se inicializa la instancia.
(deffunction filtrar-multi-por (?li ?sl ?const)
	(bind ?encontrado FALSE)
	(if (neq ?li FALSE) then
		(bind ?li (create$ ?li))
		(if (> (length ?li) 0) then
			(loop-for-count (?i 1 (length ?li))
				(bind $?v (send (nth$ ?i ?li) ?sl))
				(if (member$ ?const $?v) then
					(if (eq ?encontrado FALSE) then
						(bind ?encontrado TRUE)
						(bind ?ins (nth$ ?i ?li))
					else
						(bind ?ins (create$ ?ins (nth$ ?i ?li)))
					)
				)
			)
		)
	)
 
	(if (eq ?encontrado FALSE) then
		(bind ?ins FALSE)
	)
	(return ?ins)
)